home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / adaed-1.11 / adaed-1 / Adaed-1.11.0a / adaprs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  14.2 KB  |  504 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /*            
  10.  *                        Parser for ADA
  11.  *            
  12.  *                        Written by
  13.  *                        Nathan Glasser 
  14.  *                        Brian Siritzky
  15.  *
  16.  *
  17.  * This program is invoked with command line arguments to specify the
  18.  * Ada source file and options. The LALR(1) parser consists of a parser driver
  19.  * which uses tables produced by a parser generator. The information in the
  20.  * tables is used to initialize program arrays statically. Two stacks are
  21.  * kept as the parser performs shifts and reductions: state_stack, the state
  22.  * stack, and prs_stack, the stack of grammar symbols (tokens and non-terminals)
  23.  * and their developing abstract syntax trees. The two stacks are seperate, and
  24.  * reductions are deferred until the next shift to allow for the inclusion of
  25.  * an error recovery routine which needs to examine the symbols which 
  26.  * participated in the last reduction. Reductions are done by calling the
  27.  * reduce() function, which is generated by LALR from the file ada.g with
  28.  * the grammar and reduce actions.
  29.  *
  30.  */
  31.  
  32. #include "ada.h"
  33. #include "ifile.h"
  34. #include "miscprots.h"
  35. #include "libfprots.h"
  36. #include "actionprots.h"
  37. #include "adaredprots.h"
  38. #include "prsutilprots.h"
  39. #include "prserrprots.h"
  40. #include "adalexprots.h"
  41. #include "adaprsprots.h"
  42.  
  43. static void prsinit();
  44. static void lrparse();
  45. static void errorinit(struct two_pool **, struct two_pool **, int *);
  46.  
  47. /* Global variables */
  48.  
  49. struct prsstack *prs_stack = NULL,    /* Stack containing symbols */
  50. *curtok,        /* Current input token */
  51. *PREVTOK = NULL;    /* Previous input token */
  52. struct two_pool *sta_stack;        /* The state stack */
  53. char *strjoin();
  54. FILE *MALFILE;                /* smalloc measurement file */
  55. /* not used by parser */
  56. FILE *efopen();
  57. FILE *efopenl();
  58. IFILE *ifopen();
  59. IFILE *astfile;                /* File pointer for ast file */
  60. FILE  *adafile,                /* File pointer for ada source file */
  61. *msgfile,                /* File pointer for msgs file */
  62. *errfile;                /* File pointer for error & debug info*/
  63.  
  64. struct ast *opt_node, *any_node;    /* Special nodes to indicate
  65.                        optional elements in the ada
  66.                        syntax, or a node to be filled in */
  67. int redopt = 0;                /* Flag for printing rules */
  68. int astopt = 1;                /* Flag for printing ast */
  69. int erropt = 0;                /* Flag for printing debugging info */
  70. int termopt = 0;            /* Flag for terminal display */
  71. int debugopt = 0;            /* True if any debugging options on */
  72. int trcopt = 0;                /* True if erropt or redopt set */
  73. extern int optind;            /* global option index */
  74.  
  75. int n_sta_stack;            /* The size of the state stack */
  76. int n_prs;
  77. struct prsstack **tokens = NULL;    /* Token stack */
  78. int tokind = -1;
  79. int toksiz = 1;        /* Size of array used for token stack */
  80. int tokbottom = 0;
  81.  
  82. int err_ct = 0;
  83.  
  84. extern int optind;
  85. extern char *optarg;
  86.  
  87. int main(int argc, char **argv)                /*;main*/
  88. {
  89.     /* Variables for reading command line and figuring out names
  90.        of files, etc. */
  91.     char *adafilename = NULL;
  92.     char *sourcefilename;
  93.     char *basefilename = NULL;
  94.     char *errfilename = NULL;
  95.     char *lib_name;
  96.     char *t_name;
  97.     int  c, n, i, w_trace = 1, r_trace = 0, iot_level = 2;
  98.     int  lib_option = FALSE;
  99.     int  new_library = FALSE;
  100.     int iot_ast_w = 0; /* nonzero to trace ast tree write */
  101.     int unbufflag = 0;
  102.     int  prefix_len, base_len, suffix_len;
  103.     char *basep;
  104.  
  105.     /* The parser bombs on VAX if no arguments, so for now fail and
  106.      * also modify usage message to indicate that filename required
  107.      */
  108.  
  109.     /* Figure out what the command line means */
  110.     while ((c = getopt(argc, argv, "f:l:np:")) != EOF)
  111.     {
  112.         switch (c) {
  113.         case 'l': /* using existing library */
  114.             lib_option = TRUE;
  115.             lib_name = emalloc(strlen(optarg) + 1);
  116.             strcpy(lib_name, optarg);
  117.             break;
  118.         case 'n': /* indicates new library */
  119.             new_library = TRUE;
  120.             lib_option = TRUE;
  121.             break;
  122.         case 'f' :
  123.             n = strlen(optarg);
  124.             for (i = 0; i < n; i++) {
  125.                 switch (optarg[i]) {
  126.  
  127.                 case 'n': 
  128.                     iot_set_opt_number(0);
  129.                     break;
  130.                 case 'p': 
  131.                     if (w_trace) iot_ast_w = iot_level;
  132.                     break;
  133.                 case 'd': 
  134.                     iot_set_opt_desc(0); 
  135.                     break;
  136.                 case 'r': 
  137.                     w_trace= FALSE; 
  138.                     r_trace= TRUE; 
  139.                     break;
  140.                 case 'w': 
  141.                     r_trace = FALSE; 
  142.                     w_trace = TRUE; 
  143.                     break;
  144.                 case '1': 
  145.                     iot_level = 1; 
  146.                     break;
  147.                 case '2': 
  148.                     iot_level = 2; 
  149.                     break;
  150.                 }
  151.             }
  152.             break;
  153.         case 'p': /* parser sub options */
  154.             n = strlen(optarg);
  155.             for (i = 0; i < n; i++) {
  156.                 switch (optarg[i]) {
  157.                 case 'a' :
  158.                     astopt = 0;
  159.                     break;
  160.                 case 'b' :  /* unbuffer output */
  161.                     unbufflag = 1;
  162.                     break;
  163.                 case 'e' :
  164.                     erropt = 1 ;
  165.                     break ;
  166.                 case 'r' : /* display of reductions + source */
  167.                     redopt = 1;
  168.                     break;
  169.                     /* terminal display of source + error messages */
  170.                 case 't':
  171.                     termopt = 1;
  172.                     break;
  173.                 }
  174.             }
  175.             break;
  176.         default:
  177.             exitp(RC_ABORT);
  178.         }
  179.     }
  180.     if (optind < argc) {
  181.         adafilename = argv[optind];
  182.         basep = parsefile(adafilename, &prefix_len, &base_len, &suffix_len);
  183.         basefilename = emalloc(base_len + 1);
  184.         strncpy(basefilename, basep, base_len);
  185.         if (suffix_len == 0) { /* if suffix .ada implied */
  186.             sourcefilename = emalloc(strlen(adafilename) + 4 + 1);
  187.             strcpy(sourcefilename, adafilename);
  188.             strcat(sourcefilename, ".ada");
  189.         }
  190.         else {
  191.             sourcefilename = adafilename;
  192.         }
  193.         adafile = efopen(sourcefilename, "r", "t");
  194.     }
  195.     else {
  196.         fprintf(stderr, "Bad usage: no adafile specified.\n");
  197.         exitp(RC_ABORT);
  198.     }
  199.     t_name = libset(lib_name);
  200.     trcopt = redopt || erropt ;
  201.     debugopt = termopt || redopt || erropt ;
  202.     if (astopt)
  203.         astfile = ifopen(basefilename, "ast", "w", "p", iot_ast_w, 0);
  204.     msgfile = efopenl(basefilename, "msg", "w", "t");
  205.     if (trcopt) {
  206. #ifndef IBM_PC
  207.         errfile = efopenl(basefilename, "err", "w", "t");
  208. #else
  209.         /* write to stdout on PC */
  210.         errfile = stdout;
  211. #endif
  212.     }
  213.     else {
  214.         errfilename = NULLFILENAME ;
  215.         errfile = (FILE *)0;
  216.     }
  217.  
  218.     if (unbufflag)
  219.     {
  220.         if (astopt)
  221.             setbuf(astfile->fh_file, (char *)0);
  222.         if (trcopt)
  223.             setbuf(errfile, (char *)0);
  224.         setbuf(msgfile, (char *)0);
  225.     }
  226.  
  227.     prsinit();
  228.  
  229.     lrparse();
  230.     if (debugopt && err_ct)
  231.         printf("%d parse error(s) found.\n", err_ct);
  232.  
  233.     fclose(adafile);
  234.     if (astopt) {
  235.         putnum(astfile, "end-file", -1); /* to indicate end of file */
  236.         ifclose(astfile);
  237.     }
  238.     fclose(msgfile);
  239.     if (trcopt)
  240.         fclose(errfile);
  241.     exitp(err_ct > 0 ? RC_ERRORS : RC_SUCCESS);
  242. }
  243.  
  244. static void prsinit()                    /*;prsinit*/
  245. {
  246.     opt_node = new_node(AS_OPT);
  247.     any_node = new_node(AS_OPT);
  248. }
  249.  
  250. /* 
  251.  *            Lrparse: Parser driver. 
  252.  * Gettok() is called to return the next token.
  253.  *  Action is called to compute the next action to be taken given the
  254.  *  state and current token. If the action is a reduction, the reduction
  255.  *  of the state stack is performed, the reduction of the parse stack
  256.  *  is deferred until the next shift by putting onto the queue marked by
  257.  *  topred and lastred, and the new state is computed with another call to
  258.  *  action acting as a GOTO. If the action is a shift, all deferred reductions
  259.  *  are performed, the current token is added to the parse stack, and
  260.  *  the new state is equal to the value returned by action(). When the action
  261.  *  is shift and is equal to NUM_STATES, this is an accept action, and we 
  262.  *  return. 
  263.  */
  264.  
  265. /* 
  266.  *    A stack of tokens is kept so as to conform with the addition of an 
  267.  *  error recovery routine. Tokens is the variable which is used as an
  268.  *  array to store the tokens. Tokind is the index into this array indicating
  269.  *  the next token to be returned, or -1 if there are no stored tokens.
  270.  *  The macro NEXTTOK is designed for use with this scheme. Toksiz represents
  271.  *  the size of the array being used for the token stack at any given time.
  272.  *  If we need more space, we call realloc() to give us more storage, and
  273.  *  change toksiz to reflect this change. 
  274.  */
  275.  
  276. /*
  277.   *    Changes made for error recovery        (12/28/83-NG)
  278.   *
  279.   *  Before the call to prserr(), some manipulation of the state and
  280.   *  parse stacks must be performed. A "common point" between these
  281.   *  two stacks must be kept. Before the call to prserr(), the state
  282.   *  stack from the common point must be freed, and then increased to a 
  283.   *  size equal that of the parse stack. This is done by computing
  284.   *  states from the current top of the state stack and the corresponding
  285.   *  position in the parse stack, putting the new state on top and then
  286.   *  using it to compute the next state in the same manner.
  287.   *  This common point is implemented as follows :
  288.   *  The variable sta_com_pt is a pointer to the element of the state
  289.   *  stack which corresponds to the common point. The variable 
  290.   *  prs_com_pt_ct is an integer telling how many elements, from the top
  291.   *  of the parse stack, are needed to reach that element of the parse
  292.   *  stack corresponding to the element in the state stack pointed to
  293.   *  by sta_com_pt (in terms of the sizes of the stacks below these
  294.   *  elements). After performing a shift, sta_com_pt is NULL, and 
  295.   *  prs_com_pt_ct is 0. This is because all deferred reductions will
  296.   *  have been performed, putting the two stacks in alignment. The NULL
  297.   *  indicates that the common point is above (the top of) the state
  298.   *  stack. When there is a reduction, the sta_com_pt may shift down in
  299.   *  the stack or remain the same. If it shifts downwards, then
  300.   *  prs_com_pt_ct is shifted also by the number of elements sta_com_pt
  301.   *  was shifted. (When this first happens sta_com_pt becomes non-NULL)
  302.   *     Just before the call to prserr(), first free the elements of the 
  303.   *  state stack using the pointer we have to the last element we wish
  304.   *  freed. Then copy prs_com_pt_ct elements from the top of the parse
  305.   *  stack into an array. We then compute the states from the state on top
  306.   *  of the state stack and the next element of the parse stack (from the 
  307.   *  array).
  308.   *
  309.   */
  310.  
  311.  
  312.  
  313. static void lrparse()                /*;lrparse*/
  314. {
  315.     struct two_pool *topred = NULL,    /* Top of reduction queue */
  316.     *lastred = NULL;    /* Bottom of reduction queue */
  317.     int act;                /* Pending action */
  318.     struct two_pool *tmp, *top;        /* Temps */
  319.     int n,        /* Number of symbols being reduced */
  320.     red;        /* Reduction to be performed */
  321.     struct two_pool *sta_com_pt = NULL; /* Common point stuff */
  322.     int i;
  323.     int prs_com_pt_ct = 0;
  324.     int prs_ct_flag;
  325.  
  326.     sta_stack = TALLOC();
  327.     sta_stack->val.state = 1;
  328.     sta_stack->link = NULL;
  329.     curtok = NEXTTOK;
  330.  
  331.     while (1)            /* Main parse loop */
  332.     {
  333.         /*    Determine action */
  334.  
  335. #ifdef DEBUG1
  336.         if (trcopt) {
  337.             fprintf(errfile, "action(%d, %d) = ", sta_stack->val.state, curtok->symbol);
  338.         }
  339. #endif
  340.         act = action(sta_stack->val.state, curtok->symbol);
  341. #ifdef DEBUG1
  342.         if (trcopt)
  343.             fprintf(errfile, "%d \n", act) ;
  344. #endif
  345.  
  346.         if (!act)        /* ERROR */
  347.         {
  348.             if (topred != NULL)
  349.                 errorinit(&sta_stack, &sta_com_pt, &prs_com_pt_ct) ;
  350.  
  351.             prserr(curtok);        /* THIS IS IT : PRSERR */
  352.  
  353.             curtok = NEXTTOK ;
  354.  
  355. #ifdef DEBUG
  356.             /* print debugging information */
  357.             if (trcopt) {
  358.                 fprintf(errfile, "RECOVERED\n");
  359.                 fprintf(errfile, "STATE STACK:\n");
  360.                 dump_stack(sta_stack);
  361.                 fprintf(errfile, "PARSE STACK:\n");
  362.                 dump_prsstack(prs_stack);
  363.                 fprintf(errfile, "NEXT TOKEN: %s\n", TOKSTR(curtok->symbol));
  364.             }
  365. #endif
  366.  
  367.             /* 
  368.              * Free any pending reductions 
  369.              */
  370.             if (topred != NULL) {
  371.                 TFREE(topred, lastred) ;
  372.                 topred = lastred = NULL ;
  373.             }
  374.         }
  375.  
  376.         else if (act <= NUM_STATES) /* Shift */
  377.         {
  378.             /* Perform deferred reductions on prs_stack */
  379.  
  380.             if (topred != NULL) {
  381.  
  382.                 tmp = topred;
  383.                 while (topred != NULL) {
  384.                     reduce((int)topred->val.reduction);
  385.                     topred = topred->link;
  386.                 }
  387.                 TFREE(tmp, lastred);
  388.                 lastred = NULL;
  389.             }
  390.             tmp = TALLOC();
  391.             tmp->val.state = act;
  392.             tmp->link = sta_stack;
  393.             sta_stack = tmp ;
  394.             n_sta_stack ++ ;
  395.             curtok->prev = prs_stack;
  396.             prs_stack = curtok;
  397.             PREVTOK = copytoken(curtok) ;
  398.             curtok = NEXTTOK;
  399.             n_prs ++ ; /* Increment the size of the parse stack */
  400.  
  401.             sta_com_pt = NULL;        /* Initialize comm pt stuff */
  402.             prs_com_pt_ct = 0;
  403.  
  404.             if (act == NUM_STATES)    /* Accept */
  405.                 return;
  406.         }
  407.         else /* Reduce */
  408.         {
  409.             red = act - NUM_STATES - 1;
  410.             n = rhslen[red];
  411.             tmp = TALLOC();
  412.             tmp->val.reduction = red;
  413.             tmp->link = NULL;
  414.             prs_ct_flag = 0;
  415.             if (lastred == NULL)
  416.                 topred = lastred = tmp;
  417.             else {
  418.                 lastred->link = tmp;
  419.                 lastred = tmp;
  420.             }
  421.             if (!n) {
  422.                 tmp = TALLOC();
  423.                 tmp->link = sta_stack;
  424.                 sta_stack = tmp;
  425.             }
  426.             else if (n > 1) {
  427.                 top = sta_stack;
  428.                 n_sta_stack = n_sta_stack - n + 1 ;
  429.                 for (i = n - 2; i--; ) {
  430.                     if (sta_com_pt == sta_stack)   /* The common point */
  431.                     {                   /* might be freed here */
  432.                         sta_com_pt = NULL;
  433.                         prs_ct_flag = 1;
  434.                         prs_com_pt_ct += 2;
  435.                     }
  436.                     else if (prs_ct_flag)    /* Keep count of no. of places */
  437.                         prs_com_pt_ct++;    /* common point will move */
  438.                     sta_stack = sta_stack->link;
  439.                 }
  440.                 if (sta_com_pt == sta_stack) {
  441.                     sta_com_pt = NULL;
  442.                     prs_com_pt_ct ++ ;
  443.                 }
  444.                 tmp = sta_stack;
  445.                 sta_stack = sta_stack->link;
  446.                 TFREE(top, tmp);
  447.             }
  448.  
  449.             /* Set sta_com_pt if needed, and set prs_com_pt_ct to
  450.            point to right part of prs_stack in the case in which 
  451.            this is the first reduction after a shift. */
  452.             if (sta_com_pt == NULL) {
  453.                 sta_com_pt = sta_stack;
  454.                 if (!prs_com_pt_ct)
  455.                     prs_com_pt_ct = n ;
  456.             }
  457.  
  458.             sta_stack->val.state = 
  459.                 action((int)sta_stack->link->val.state, lhs[red]);
  460.         }
  461.     }
  462. }
  463.  
  464. static void errorinit(struct two_pool **psta_stack,
  465.   struct two_pool **psta_com_pt, int *pprs_com_pt_ct)    /*;errorinit*/
  466. {
  467.     struct two_pool *tmp;
  468.     struct prsstack **tmp_prs_array;
  469.     struct prsstack *prs_temp;
  470.     int i;
  471.  
  472.     if (*psta_com_pt == NULL)
  473.         return;
  474.     tmp = (*psta_com_pt)->link;
  475.     TFREE(*psta_stack, *psta_com_pt);
  476.     *psta_stack = tmp;
  477.     *psta_com_pt = NULL;
  478.     if (!*pprs_com_pt_ct)
  479.         return;
  480.     tmp_prs_array = (struct prsstack **)malloc((unsigned)(*pprs_com_pt_ct * 
  481.       (sizeof(struct prsstack *))));
  482.     for (i = 0, prs_temp = prs_stack; i < *pprs_com_pt_ct; i++,
  483.       prs_temp = prs_temp->prev)
  484.         tmp_prs_array[i] = prs_temp;
  485.     for (i = *pprs_com_pt_ct - 1; i >= 0; i--) {
  486.         tmp = TALLOC();
  487.         tmp->link = *psta_stack;
  488.         tmp->val.state = action((int)(*psta_stack)->val.state,
  489.           tmp_prs_array[i]->symbol);
  490.         *psta_stack = tmp;
  491.     }
  492.     free((char *)tmp_prs_array);
  493.     *pprs_com_pt_ct = 0;
  494. }
  495.  
  496. struct prsstack *tokfromlist()            /*;tokfromlist*/
  497. {
  498.     int tmp = tokind;
  499.  
  500.     tokind = (tokind - 1 + toksiz) % toksiz;
  501.     return(tokens[tmp]);
  502. }
  503.  
  504.